﻿
namespace EasyNet.Solr.Impl
{
    using System.Linq;
    using System.Runtime.Serialization.Json;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;

    using Commons;

    /// <summary>
    /// json格式返回数据查询结果解析器
    /// </summary>
    /// <typeparam name="T">查询结果类型</typeparam>
    public class JsonQueryResultsParser<T> : ISolrResponseParser<string, QueryResults<T>>
    {
        /// <summary>
        /// 对象反序列化器
        /// </summary>
        private readonly IObjectDeserializer<T> objectDeserialize;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="objectDeserialize">对象反序列化器</param>
        public JsonQueryResultsParser(IObjectDeserializer<T> objectDeserialize)
        {
            this.objectDeserialize = objectDeserialize;
        }

        /// <summary>
        /// 解析
        /// </summary>
        /// <param name="result">json格式字符串结果</param>
        /// <returns>查询结果</returns>
        public QueryResults<T> Parse(string result)
        {
            if (string.IsNullOrEmpty(result))
            {
                return null;
            }

            var bytes = Encoding.UTF8.GetBytes(result);

            using (var reader = JsonReaderWriterFactory.CreateJsonReader(bytes, XmlDictionaryReaderQuotas.Max))
            {
                var xmlDoc = XDocument.Load(reader);
                var queryResults = new QueryResults<T>();

                var response = xmlDoc.Root.Element("response");

                if (response == null)
                {
                    return null;
                }

                var solrDocumentList = new SolrDocumentList()
                {
                    NumFound = long.Parse(response.Element("numFound").Value),
                    Start = long.Parse(response.Element("start").Value)
                };

                var maxScore = response.Element("maxScore");

                if (maxScore != null)
                {
                    solrDocumentList.MaxScore = float.Parse(maxScore.Value);
                }

                queryResults.NumFound = solrDocumentList.NumFound;
                queryResults.MaxScore = solrDocumentList.MaxScore;

                var docs = response.Elements("docs");

                if (docs != null)
                {
                    var docItems = docs.Elements("item");

                    foreach (var docItem in docItems)
                    {
                        var doc = new SolrDocument();

                        var items = docItem.Elements();

                        foreach (var item in items)
                        {
                            var type = item.Attribute("type").Value;
                            var name = item.Name.LocalName;
                            var value = item.Value;

                            if (type != "array")
                            {
                                doc.Add(name, value);
                            }
                            else
                            {
                                doc.Add(name, (from e in item.Elements() select e.Value).ToList<string>());
                            }
                        }

                        solrDocumentList.Add(doc);
                    }


                    var objs = objectDeserialize.Deserialize(solrDocumentList);

                    foreach (T obj in objs)
                    {
                        queryResults.Add(obj);
                    }
                }

                return queryResults;
            }
        }
    }
}
